package com.xu.tools.util;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author xuguan
 * @date 2023/2/2
 * @desc Jwt工具类
 */
public class JwtUtil {
    /**
     * 私钥
     */
    public static final String secret = "abcdefg";

    /**
     * header头部
     */
    public static final Map<String, Object> headerClaimMap = new HashMap<>(8);

    /**
     * 签名
     */
    public static final Algorithm algorithm = Algorithm.HMAC256(secret);

    /**
     * token默认24小时失效
     */
    public static final long expire = 24 * 60L;

    static {
        headerClaimMap.put("alg", algorithm.getName());
        headerClaimMap.put("typ", "JWT");
    }

    public static String createJwt(Map<String, String> claimMap) {
        return createJwt(claimMap, new Date(System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(expire)));
    }

    public static String createJwt(Map<String, String> claimMap, Date expireAt) {
        // 头信息
        JWTCreator.Builder builder = JWT.create()
                .withHeader(headerClaimMap);

        // 有效载荷
        if (claimMap != null && !claimMap.isEmpty()) {
            for (Map.Entry<String, String> entry : claimMap.entrySet()) {
                builder
                        .withClaim(entry.getKey(), entry.getValue());
            }
        }

        // 签名
        return builder
                .withExpiresAt(expireAt)
                .sign(algorithm);
    }

    public static DecodedJWT verifyJwt(String jwt) throws JWTVerificationException {
        return JWT.require(algorithm).build()
                .verify(jwt);
    }

    public static Claim getClaim(String jwt, String key) {
        return getClaimMap(jwt).get(key);
    }

    public static Map<String, Claim> getClaimMap(String jwt) {
        return verifyJwt(jwt)
                .getClaims();
    }

    public static String getSubject(String jwt) {
        return verifyJwt(jwt).getSubject();
    }

    public static Date getExpireAt(String jwt) {
        return verifyJwt(jwt).getExpiresAt();
    }

    public static String getStrValue(String jwt, String key) {
        return getClaim(jwt, key).asString();
    }

    public static <T> T getObjValue(String jwt, String key, Class<T> clazz) {
        return getClaim(jwt, key).as(clazz);
    }

    public static void main(String[] args) {
        Map<String, String> claimMap = new HashMap<>(8);
        claimMap.put("userId", "123456");
        claimMap.put("userName", "zhang san");
        String jwt = createJwt(claimMap);
        String userId = getStrValue(jwt, "userId");
        Date expireAt = getExpireAt(jwt);
        System.out.println("jwt = " + jwt);
        System.out.println("userId = " + userId);
        System.out.println("expireAt = " + expireAt);
    }
}
